﻿/*************************************************
* 文 件 名：NodesData
* 命名空间：WSNs
* 功    能：
* 作    者：ZGW (zgw@cqu.edu.cn)
* 团    队：Wireless Sensor Networks (WSNs)
* 创建时间：2015/1/4 19:36:55
* 版 本 号：V1.0.0.0
* 修改日志：
*************************************************/

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WSNs
{
    class NodesData
    {
        //这个类设置为只能存在唯一实例，并可以在全局里调用
        private static readonly NodesData _nodesData = new NodesData();
        public Dictionary<int, bool> _nodeIsLive = new Dictionary<int, bool>(); //定时器每隔6秒检查一次节点是否在线
        private NodesData() { }

        /// <summary>
        /// 获取对节点数据实例
        /// </summary>
        /// <returns></returns>
        public static NodesData GetInstance()
        {
            return _nodesData;
        }

        #region Fields

        /// <summary>
        /// 保存每个节点的绘图控件
        /// </summary>
        private readonly Dictionary<int, CtlDataDrawer> _dicNodeCtl = new Dictionary<int, CtlDataDrawer>();

        /// <summary>
        /// 保存每个节点的FFT控件
        /// </summary>
        private readonly Dictionary<int, CtlDataFft> _dicNodeFFT = new Dictionary<int, CtlDataFft>();

        /// <summary>
        /// 存储原始数据
        /// </summary>
        private readonly Dictionary<int, List<byte>> _dicNodesData = new Dictionary<int, List<byte>>();
        
        /// <summary>
        /// 存储转换后的float数据
        /// </summary>
        private readonly Dictionary<int, List<float>> _dicNodesFloatData = new Dictionary<int, List<float>>();

        /// <summary>
        /// 存储每个节点的放大倍数
        /// </summary>
        private readonly Dictionary<int, float> _dicNodesMeasuerRange = new Dictionary<int, float>();
        /// <summary>
        /// 融合结果数据
        /// </summary>
        private Dictionary<int, List<byte>> _dicFusionData = new Dictionary<int, List<byte>>();
        /// <summary>
        /// 保存哪些节点显示
        /// </summary>
        private List<int> _listNodeToShow = new List<int>();

        /// <summary>
        /// 保存添加数据中多出的字节
        /// </summary>
        private List<byte> _listOverByte = new List<byte>();

        /// <summary>
        /// 保存节点的文件目录
        /// </summary>
        private readonly Dictionary<int, List<string>> _dicNodeDir = new Dictionary<int, List<string>>();

        /// <summary>
        /// 保存节点的灵敏度
        /// </summary>
        private readonly Dictionary<int, double> _dicSensitivity = new Dictionary<int, double>();

        /// <summary>
        /// 保存节点的采集参数
        /// </summary>
        private readonly Dictionary<int, AcqStructure> _dicNodeAcq = new Dictionary<int, AcqStructure>();


        private const float ScaleShort2Float = 1.0f/4096*3.3f;
        private float scaleInt2Float = 1.0f / 8388608 * 5f;
        private const float MeanFloat = 1.65f;

        #endregion

        /// <summary>
        /// 更新节点放大倍数
        /// </summary>
        /// <param name="node">节点ID，0为所有节点</param>
        /// <param name="m">PGA113放大参数</param>
        public void SetMeasuerRange(int node, int m)
        {
            float measuerRange;
            switch (m)
            {
                case 0:
                    measuerRange = 0.5f;
                    break;
                case 1:
                    measuerRange = 1;
                    break;
                case 2:
                    measuerRange = 2.5f;
                    break;
                case 3:
                    measuerRange = 5;
                    break;
                case 4:
                    measuerRange = 10;
                    break;
                case 5:
                    measuerRange = 25;
                    break;
                case 6:
                    measuerRange = 50;
                    break;
                case 7:
                    measuerRange = 100;
                    break;
                default:
                    measuerRange = 1;
                    break;
            }

            if (node == 0) //更新所有
            {
                foreach (int key in _dicNodeCtl.Keys)
                {
                    if (!_dicNodesMeasuerRange.Keys.Contains(key))
                        _dicNodesMeasuerRange.Add(key, measuerRange);
                    else
                        _dicNodesMeasuerRange[key] = measuerRange;
                }
                return;
            }
            if (!_dicNodesMeasuerRange.Keys.Contains(node))
                _dicNodesMeasuerRange.Add(node, measuerRange);
            else
                _dicNodesMeasuerRange[node] = measuerRange;
        }

        public float GetMeasuerRange(int node)
        {
            return _dicNodesMeasuerRange.Keys.Contains(node) ? _dicNodesMeasuerRange[node] : 1;
        }

        public void AddNode(CtlNode acq)
        {
            if (_dicNodeCtl.ContainsKey(acq.NodeID))
            {
                MessageBox.Show("节点" + acq.NodeID.ToString() + "已存在");
                return;
            }
            //添加显示控件
            CtlDataDrawer ctlDataDrawer = new CtlDataDrawer(acq.AcqStructure); //todo:改为通道判断
            //添加数据节点控件
            ctlDataDrawer.InitTitle("节点:" + acq.NodeID.ToString() + " @ " + acq.AcqStructure.Frequency + "Hz", "时间", "s", "振幅", "g");
            _dicNodeCtl.Add(acq.NodeID, ctlDataDrawer);
            if (!_nodeIsLive.ContainsKey(acq.NodeID))
            {
                _nodeIsLive.Add(acq.NodeID, true);
            }
            else 
            {
                _nodeIsLive[acq.NodeID] = true;
            }
            _dicNodesFloatData.Add(acq.NodeID, new List<float>());
            if (_dicSensitivity.ContainsKey(acq.NodeID))
            {
                _dicSensitivity[acq.NodeID] = 1000;
            }
            else
            {
                _dicSensitivity.Add(acq.NodeID, 1000);
            }
            
;            //在显示中添加
            _listNodeToShow.Add(acq.NodeID);

            if (acq.NodeType == NodesType.Router) return;
            //添加FFT控件
            acq.NodeType = NodesType.FFTNode;
            CtlDataFft ctlFFT = new CtlDataFft(acq.AcqStructure);
            ctlFFT.InitTitle("节点:" + acq.NodeID.ToString() + " FFT @ " + acq.AcqStructure.Frequency + "Hz", "频率", "Hz", "振幅", "g");
            _dicNodeFFT.Add(acq.NodeID, ctlFFT);
            acq.NodeType = NodesType.EndNode;
        }

        public void AddSignal(int Node, int value)
        {
            if (!_dicNodeCtl.ContainsKey(Node))
            {
                //MessageBox.Show("节点" + Node.ToString() + "不存在");
                return;
            }
            //获取相应节点控件
            CtlDataDrawer Temp = GetDataDrawer(Node);
            Temp.SignalValue = value;

        }

        /// <summary>
        ///向指定节点添加数据
        /// </summary>
        /// <param name="nodeID">节点ID</param>
        /// <param name="bData">字节型数据</param>
        /// <param name="isLive">是否实时显示</param>
        /// <param name="type">数据类型</param>
        
        public void AddData(int nodeID,List<byte> lbData,bool isLive,DataType type)
        {
            int count;
            float[] acqFloatData;
            byte[] bData;
            ushort utmp;
            float sensitivity = (float)_dicSensitivity[nodeID];
            switch (type)
            {
                case DataType.DaqData:
                    bData = lbData.ToArray();
                    acqFloatData = new float[bData.Length / 4];
                    for (int i = 0; i < bData.Length; i += 4)
                    {
                        float tmp = BitConverter.ToSingle(bData, i);
                        acqFloatData[i / 4] = tmp/10;
                    }
                    _dicNodesFloatData[nodeID].AddRange(acqFloatData);
                    _dicNodeCtl[nodeID].AddaData(acqFloatData.ToList(), isLive);
                    break;
                case DataType.Signed16:
                    lbData.InsertRange(0,_listOverByte);
                    count = lbData.Count / 2; //需要取走的数据个数
                    acqFloatData = new float[count];
                    bData = lbData.ToArray();
                    for (int i = 0; i < count * 2; i += 2)
                    {
                        utmp = BitConverter.ToUInt16(bData, i);
                        acqFloatData[i / 2] = utmp * ScaleShort2Float - MeanFloat;

                    }
                    _dicNodesFloatData[nodeID].AddRange(acqFloatData);
                    _dicNodeCtl[nodeID].AddaData(acqFloatData.ToList(), isLive);
                    //保存未处理的字节
                    _listOverByte.Clear();
                    if (count * 2 < lbData.Count)
                    {
                        _listOverByte.AddRange(lbData.GetRange(count, lbData.Count - count));
                    }
                    break;
                case DataType.Signed24:
                    lbData.InsertRange(0,_listOverByte);
                    count = lbData.Count / 3; //需要取走的数据个数
                    acqFloatData = new float[count];
                    byte[] byteData = new byte[4] { 0, 0, 0, 0 };
                    //float[] acqFloatData = new float[acqData.Length / 3];
                    //int lengthtemp = acqData.Length % 3;
                    for (int i = 0; i < count * 3; i += 3)
                    {
                        byteData[0] = lbData[i];
                        byteData[1] = lbData[i + 1];
                        byteData[2] = lbData[i + 2];
                        byteData[3] = (byteData[2] & 0x80) == 0 ? (byte) 0x00 : (byte) 0xff;
                        Int32 tmp = BitConverter.ToInt32(byteData, 0);
                        acqFloatData[i / 3] = (tmp  );
                    }
                    _dicNodesFloatData[nodeID].AddRange(acqFloatData);
                    _dicNodeCtl[nodeID].AddaData(acqFloatData.ToList(), isLive);
                    //保存未处理的字节
                    _listOverByte.Clear();
                    if (count * 3 < lbData.Count)
                    {
                        _listOverByte.AddRange(lbData.GetRange(count, lbData.Count - count));
                    }
                    break;
                case DataType.Unsigned16:
                    lbData.InsertRange(0,_listOverByte);
                    count = lbData.Count / 2; //需要取走的数据个数
                    acqFloatData = new float[count];
                    bData = lbData.ToArray();
                    for (int i = 0; i < count * 2; i += 2)
                    {
                        utmp = BitConverter.ToUInt16(bData, i);
                        acqFloatData[i/2] = (utmp*ScaleShort2Float - MeanFloat)/GetMeasuerRange(nodeID)/1.044f;
                        //acqFloatData[i / 2] = utmp;
                    }
                    _dicNodesFloatData[nodeID].AddRange(acqFloatData);
                    _dicNodeCtl[nodeID].AddaData(acqFloatData.ToList(), isLive);
                    //保存未处理的字节
                    _listOverByte.Clear();
                    if (count * 2 < lbData.Count)
                    {
                        _listOverByte.AddRange(lbData.GetRange(count, lbData.Count - count));
                    }
                    break;
            }
        }

        /// <summary>
        /// 更新指定节点FFT数据
        /// </summary>
        /// <param name="nodeID">节点ID</param>
        /// <param name="frequency">采样率</param>
        /// <param name="startPoint">起始点</param>
        /// <param name="lfData">要进行FFT的数据</param>
        public void UpdataFft(int nodeID, float frequency, int startPoint, List<float> lfData)
        {
            //ushort utemp;

           // for (int k = 0; k < lfData.Count; k++)
          //  {
              //  lfData[k] = (lfData[k] * ScaleShort2Float - MeanFloat) / GetMeasuerRange(nodeID) / 1.044f;
           // }
                _dicNodeFFT[nodeID].UpdataData(frequency, startPoint, lfData);
        }

        /// <summary>
        /// 更新显示标题频率
        /// </summary>
        /// <param name="fre">频率</param>
        /// <param name="node">指定节点或所有节点（0为所有节点）</param>
        public void UpdataTitle(float fre,int node)
        {
            if (node == 0)
            {
                foreach (int i in _dicNodeCtl.Keys)
                {
                    _dicNodeCtl[i].InitTitle("节点:" + i.ToString() + " @ " + fre.ToString() + "Hz", "时间", "s", "振幅","g");
                    _dicNodeFFT[i].InitTitle("节点:" + i.ToString() + " FFT @ " + fre.ToString() + "Hz", "频率", "Hz", "振幅","g");
                    _dicNodeCtl[i].Frequence = fre;
                    //_dicNodeFFT[i].Frequence = fre; //todo: 待添加
                }
            }
            else
            {
                if (!_dicNodeCtl.Keys.Contains(node)) return;
                _dicNodeCtl[node].InitTitle("节点:" + node.ToString() + " @ " + fre.ToString() + "Hz", "时间", "s", "振幅","g");
                _dicNodeFFT[node].InitTitle("节点:" + node.ToString() + " FFT @ " + fre.ToString() + "Hz", "频率", "Hz", "振幅","g");
                _dicNodeCtl[node].Frequence = fre;
                //_dicNodeFFT[i].Frequence = fre; //todo: 待添加
            }
        }

        public void RemoveAllNode()
        {
            _dicNodesFloatData.Clear();
            _dicNodeCtl.Clear();
            _dicNodeFFT.Clear();
            _listNodeToShow.Clear();
            _listOverByte.Clear();
            _dicNodesData.Clear();
            _dicSensitivity.Clear();
            _dicNodeAcq.Clear();
        }

        /// <summary>
        /// 移除选中节点
        /// </summary>
        /// <param name="id"></param>
        public void RemoveSelectedNode(int id)
        {
            _dicNodesFloatData.Remove(id);
            _dicNodeCtl.Remove(id);
            _dicNodeFFT.Remove(id);
            _listNodeToShow.Remove(id);
            _dicNodesData.Clear();
            _dicSensitivity.Remove(id);
            _dicNodeAcq.Remove(id);
        }
        /// <summary>
        /// 获取节点数据显示控件
        /// </summary>
        /// <param name="nodeID"></param>
        /// <returns></returns>
        public CtlDataDrawer GetDataDrawer(int nodeID)
        {
            return _dicNodeCtl[nodeID];
        }

        /// <summary>
        /// 获取FFT控件
        /// </summary>
        /// <param name="nodeID"></param>
        /// <returns></returns>
        public CtlDataFft GetFFTDrawer(int nodeID)
        {
            return _dicNodeFFT[nodeID];
        }

        public bool ContainsNode(int nodeID)
        {
            return _dicNodeCtl.ContainsKey(nodeID);
        }

        public List<int> GetAllnodes()
        {
            return _dicNodeCtl.Keys.ToList();
        }
        /// <summary>
        /// 获取所有的显示节点(不一定是所有节点)
        /// </summary>
        /// <returns></returns>
        public List<int> GetShowNodes()
        {
            return _listNodeToShow;
        }

        public void AddShowNode(int nodeID)
        {
            if (_listNodeToShow.Contains(nodeID)) return;
            _listNodeToShow.Add(nodeID);
        }

        public void RemoveShowNode(int nodeID)
        {
            if (!_listNodeToShow.Contains(nodeID)) return;
            _listNodeToShow.Remove(nodeID);
        }

        /// <summary>
        /// 存储原始数据
        /// </summary>
        /// <param name="i">节点ID</param>
        /// <param name="lb">原始数据包</param>
        public void SaveAllData(int i, List<byte> lb)
        {
            if (_dicNodesData.Keys.Contains(i))
                _dicNodesData[i].AddRange(lb);
            else
                _dicNodesData.Add(i, lb);
        }

        /// <summary>
        /// 获取原始字节型数据
        /// </summary>
        /// <returns></returns>
        public List<byte> GetAllByteData(int i)
        {
            return _dicNodesData[i];
        }

        /// <summary>
        /// 获取节点收到的最后一个数据包序列号
        /// </summary>
        /// <param name="nodeID">节点ID</param>
        /// <param name="packLength">数据包长度，包括 0xAA 0x55 ...</param>
        /// <returns>最后一个包的序列号</returns>
        public UInt16 GetLastSerial(int nodeID, int packLength)
        {
            if (_dicNodesData.Keys.Contains(nodeID) && _dicNodesData[nodeID].Count >= packLength)
                return BitConverter.ToUInt16(
                        _dicNodesData[nodeID].GetRange(_dicNodesData[nodeID].Count - packLength + 6, 2).ToArray(), 0);
            return 0;
        }

        /// <summary>
        /// 获取浮点型数据
        /// </summary>
        /// <returns></returns>
        public Dictionary<int, List<float>> GetAllFloatData()
        {
            return _dicNodesFloatData;
        }

        /// <summary>
        /// 获取节点的目录列表
        /// </summary>
        /// <param name="nodeID"></param>
        /// <returns></returns>
        public List<string> GetNodeDir(int nodeID)
        {
            return _dicNodeDir[nodeID];
        }

        /// <summary>
        /// 保存节点目录列表
        /// </summary>
        /// <param name="nodeID"></param>
        /// <param name="s"></param>
        public void SaveNodeDir(int nodeID,string s)
        {
            if (_dicNodeDir.Keys.Contains(nodeID))
            {
                if (!_dicNodeDir[nodeID].Contains(s))
                    _dicNodeDir[nodeID].Add(s);
            }  
            else
            {
                _dicNodeDir.Add(nodeID, new List<string>());
                _dicNodeDir[nodeID].Add(s);
            }
        }

        /// <summary>
        /// 清除节点目录列表
        /// </summary>
        public void ClearNodeDir()
        {
            List<int> lTemp = _dicNodeDir.Keys.ToList();
            foreach(int i in lTemp)
            {
                _dicNodeDir[i].Clear();
            }
        }
        /// <summary>
        /// 获取指定节点的融合数据
        /// </summary>
        /// <param name="nodeID"></param>
        /// <returns></returns>
        public List<byte> GetFusionData(int nodeID)
        {
            return _dicFusionData[nodeID];
        }

        /// <summary>
        /// 保存融合结果
        /// </summary>
        /// <param name="nodeID"></param>
        /// <param name="lb"></param>
        /// <returns></returns>
        public void SaveFusionData(int nodeID, List<byte> lb)
        {
            if (_dicFusionData.Keys.Contains(nodeID))
            {
                _dicFusionData[nodeID].AddRange(lb);
            }
            else
            {
                _dicFusionData.Add(nodeID, new List<byte>());
                _dicFusionData[nodeID].AddRange(lb);
            }
        }

        /// <summary>
        /// 清除该节点数据
        /// </summary>
        /// <param name="nodeID"></param>
        public void ClearFusionData(int nodeID)
        {
            _dicFusionData[nodeID].Clear();
        }

        //设置节点的灵敏度
        public void SetSensitivity(int nodeID,double sensitivity)
        {
            if(_dicSensitivity.Keys.Contains(nodeID))
            {
                _dicSensitivity[nodeID] = sensitivity;
            }
            else
            {
                _dicSensitivity.Add(nodeID, sensitivity);
            }
        }
        /// <summary>
        /// 设置节点采集参数
        /// </summary>
        /// <param name="nodeID"></param>
        /// <param name="acq"></param>
        public void SetNodeAcq(AcqStructure acq)
        {
            List<int> NodeID = _dicNodeAcq.Keys.ToList();
            if (acq.NodeID == 0)
            {
                foreach (var i in NodeID)
                {
                    _dicNodeAcq[i] = acq;
                }
            }
            else
            {
                if (_dicNodeAcq.ContainsKey(acq.NodeID))
                {
                    _dicNodeAcq[acq.NodeID] = acq;
                }
                else
                {
                    _dicNodeAcq.Add(acq.NodeID, acq);
                }
            }
        }
        /// <summary>
        /// 获取采集参数
        /// </summary>
        /// <returns></returns>
        public Dictionary<int, AcqStructure> GetAllNodeAcq()
        {
            return _dicNodeAcq;
        }
        /// <summary>
        /// 清除所有节点的数据
        /// </summary>
        public void ClearAllNodeData()
        {
            _dicNodesFloatData.Clear();
            _listOverByte.Clear();
            _dicNodesData.Clear();
            foreach (var item in _dicNodeCtl)
            {
                item.Value.ClearData();
            }
        }
    }
}
